/*
 * Copyright (c) 2011-2021, baomidou (jobob@qq.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.hbhk.hms.mq.tx.mq;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * Collection工具类
 *
 * @author Caratacus
 * @since 2016-09-19
 */
public class CollectionUtils {

	private static final int MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2);

	/**
	 * 校验集合是否为空
	 *
	 * @param coll 入参
	 * @return boolean
	 */
	public static boolean isEmpty(Collection<?> coll) {
		return (coll == null || coll.isEmpty());
	}

	/**
	 * 校验集合是否不为空
	 *
	 * @param coll 入参
	 * @return boolean
	 */
	public static boolean isNotEmpty(Collection<?> coll) {
		return !isEmpty(coll);
	}

	/**
	 * 判断Map是否为空
	 *
	 * @param map 入参
	 * @return boolean
	 */
	public static boolean isEmpty(Map<?, ?> map) {
		return (map == null || map.isEmpty());
	}

	/**
	 * 判断Map是否不为空
	 *
	 * @param map 入参
	 * @return boolean
	 */
	public static boolean isNotEmpty(Map<?, ?> map) {
		return !isEmpty(map);
	}

	/**
	 * 创建默认HashMap
	 *
	 * @param <K> K
	 * @param <V> V
	 * @return HashMap
	 * @see com.google.common.collect.Maps#newHashMap()
	 * @since 3.4.0
	 */
	public static <K, V> HashMap<K, V> newHashMap() {
		return new HashMap<>();
	}

	/**
	 * 根据预期大小创建HashMap.
	 *
	 * @param expectedSize 预期大小
	 * @param <K>          K
	 * @param <V>          V
	 * @return HashMap
	 * @see com.google.common.collect.Maps#newHashMapWithExpectedSize
	 * @since 3.4.0
	 */
	public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
		return new HashMap<>(capacity(expectedSize));
	}

	/**
	 * 用来过渡下Jdk1.8下ConcurrentHashMap的性能bug
	 * https://bugs.openjdk.java.net/browse/JDK-8161372
	 *
	 * @param concurrentHashMap ConcurrentHashMap 没限制类型了，非ConcurrentHashMap就别调用这方法了
	 * @param key               key
	 * @param mappingFunction   function
	 * @param <K>               k
	 * @param <V>               v
	 * @return V
	 * @since 3.4.0
	 */
	public static <K, V> V computeIfAbsent(Map<K, V> concurrentHashMap, K key,
			Function<? super K, ? extends V> mappingFunction) {
		V v = concurrentHashMap.get(key);
		if (v != null) {
			return v;
		}
		return concurrentHashMap.computeIfAbsent(key, mappingFunction);
	}

	/**
	 * Returns a capacity that is sufficient to keep the map from being resized as
	 * long as it grows no larger than expectedSize and the load factor is >= its
	 * default (0.75).
	 *
	 * @see com.google.common.collect.Maps#capacity(int)
	 * @since 3.4.0
	 */
	private static int capacity(int expectedSize) {
		if (expectedSize < 3) {
			if (expectedSize < 0) {
				throw new IllegalArgumentException("expectedSize cannot be negative but was: " + expectedSize);
			}
			return expectedSize + 1;
		}
		if (expectedSize < MAX_POWER_OF_TWO) {
			// This is the calculation used in JDK8 to resize when a putAll
			// happens; it seems to be the most conservative calculation we
			// can make. 0.75 is the default load factor.
			return (int) ((float) expectedSize / 0.75F + 1.0F);
		}
		return Integer.MAX_VALUE; // any large value
	}
}
